package com.mdd.front.config.wechat;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.mdd.common.exception.OperateException;
import com.mdd.common.utils.ConfigUtil;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.security.MessageDigest;
import java.util.Map;

/**
 * @author kn4im3
 * @date 2023/3/10 09:31
 */
@Component
public class WxMpUtil {
    @Getter
    protected static String jsSdkAccessTokenUrl;
    @Getter
    protected static String jsSdkGetTicketUrl;
    
    @Value("${wx.mp.jsSdkAccessTokenUrl}")
    public void setJsSdkAccessTokenUrl(String jsSdkAccessTokenUrl) {
        this.jsSdkAccessTokenUrl = jsSdkAccessTokenUrl;
    }

    @Value("${wx.mp.jsSdkGetTicketUrl}")
    public void setJsSdkGetTicketUrl(String jsSdkGetTicketUrl) {
        this.jsSdkGetTicketUrl = jsSdkGetTicketUrl;
    }

    /**
     *@Author: kN4im3
     *@CreateTime: 21:31 2020/2/14
     *@param:  * @param null
     *@Description:

     */
    public static String getJSSDKAccessToken(String payChannel) {
        String token = null;
        Map<String, String> channel = ConfigUtil.get(payChannel);
        String appId = channel.get("appId");
        String appSecret = channel.get("appSecret");
        String url = jsSdkAccessTokenUrl.replaceAll("APPID",
                appId).replaceAll("APPSECRET",
                appSecret);
        String json = postRequestForWeiXinService(url);
        Map map = jsonToMap(json);
        if (map != null) {
            token = (String) map.get("access_token");
        }
        if (token == null){
            throw new OperateException(json);
        }
        return token;
    }

    /**
     *@Author: kN4im3
     *@CreateTime: 21:40 2020/2/14
     *@param:  * @param null
     *@Description: 根据accessToken获取JssdkGetticket

     */
    public static String getJsSdkGetTicket(String accessToken) {
        String url = jsSdkGetTicketUrl.replaceAll("ACCESS_TOKEN", accessToken);
        String json = postRequestForWeiXinService(url);
        Map map = jsonToMap(json);
        String jsapi_ticket = null;
        if (map != null) {
            jsapi_ticket = (String) map.get("ticket");
        }
        return jsapi_ticket;
    }

    /**
     *@Author: kN4im3
     *@CreateTime: 21:41 2020/2/14
     *@param:ticket 根据accessToken生成的JsSdkGetTicket
     *@param:timestamp 支付签名时间戳，注意微信jsSdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
     *@param:nonceStr 随机字符串
     *@param:url 当前网页的URL
     *@Description: 构建分享链接的签名

     */
    public static String buildJSSDKSignature(String ticket,String timestamp,String nonceStr ,String url) throws Exception {
        String orderedString = "jsapi_ticket=" + ticket
                + "&noncestr=" + nonceStr + "&timestamp=" + timestamp
                + "&url=" + url;
        return sha1(orderedString);
    }

    /**
     * sha1 加密JSSDK微信配置参数获取签名。
     *
     * @return
     */
    public static String sha1(String orderedString) throws Exception {
        String ciphertext = null;
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        byte[] digest = md.digest(orderedString.getBytes());
        ciphertext = byteToStr(digest);
        return ciphertext.toLowerCase();
    }
    /**
     * 将字节数组转换为十六进制字符串
     *
     * @param byteArray
     * @return
     */
    private static String byteToStr(byte[] byteArray) {
        String strDigest = "";
	    for (byte b : byteArray) {
		    strDigest += byteToHexStr(b);
	    }
        return strDigest;
    }
    /**
     * 将字节转换为十六进制字符串
     *
     * @param mByte
     * @return
     */
    private static String byteToHexStr(byte mByte) {
        char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
        char[] tempArr = new char[2];
        tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
        tempArr[1] = Digit[mByte & 0X0F];

        String s = new String(tempArr);
        return s;
    }
    /**
     *@Author: kN4im3
     *@CreateTime: 21:49 2020/2/14
     *@param:  map
     *@Description:  mapToJson

     */
    public static String mapToJson(Map map){
        Gson gson = new Gson();
        String json = gson.toJson(map);
        return json;
    }

    /**
     *@Author: kN4im3
     *@CreateTime: 21:37 2020/2/14
     *@param:  json
     *@Description: jsonToMap

     */
    private static Map jsonToMap(String json) {
        Gson gons = new Gson();
        Map map = gons.fromJson(json, new TypeToken<Map>(){}.getType());
        return map;
    }

    /**
     *@Author: kN4im3
     *@CreateTime: 21:36 2020/2/14
     *@param:  * @param null
     *@Description: 调取微信接口

     */
    private static String postRequestForWeiXinService(String getAccessTokenUrl) {
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> postForEntity = restTemplate.postForEntity(getAccessTokenUrl, null, String.class);
        String json = postForEntity.getBody();
        return json;
    }
}
